﻿#pragma once

#include <memory>
#include "Containers/SharedObjectPtr.h"
#include "Object/Object.h"
#include "Font/CharTexture.h"
#include "TextTexturePool.m.h"

struct SFreeTypeGlyph;
class RTexture2D;
class RTextTexturePool;


class CTextureTreeNode : public std::enable_shared_from_this<CTextureTreeNode>
{
public:
    //区域的大小
    uint16_t Size=0;
    

    //子区域,分别是左上(0)，左下(1),右上(2)，右下(3)
    //子区域在父区域中的位置是0b01(第一位代表左右，0代表左，1代表右,第二位代表上下，0代表上,1代表下)
    //如果一个区域是完全空闲的，那么这个区域的子区域都是nullptr
    std::shared_ptr<CTextureTreeNode> SubArea[4]={nullptr,nullptr,nullptr,nullptr};
    std::weak_ptr<CTextureTreeNode> Parent;

    //树对应的纹理纹理
    TSharedObjectPtr<RTexture2D> Texture;

    //区域在图片中的绝对位置,单位像素
    uint32_t X=0;
    uint32_t Y=0;
};

struct SCharKey
{
    uint16_t FontSize=0;
    uint32_t CharCode=0;

    bool operator==(const SCharKey& InOther) const
    {
        return FontSize==InOther.FontSize && CharCode==InOther.CharCode;
    }

    uint64_t GetHashCode() const
    {
        return (uint64_t)FontSize<<32 | CharCode;
    }

};

RCLASS()
class RTextTexturePool : public RObject
{
    ROBJECT
public:
    RTextTexturePool();

    static int32_t GetTextureSize();

    //查找和添加字符纹理
    SCharTexture FindOrCreate(std::shared_ptr<SFreeTypeGlyph> CharGlyph);
protected:
    //空闲的纹理树节点 [大小],[节点]
    //相同大小的节点放在同一个链表中
    //大小分别为16,32,64,128,256,512,1024
    TVector<std::list<std::shared_ptr<CTextureTreeNode>>> EmptyNodes;

    std::shared_ptr<CTextureTreeNode> Ocuppy(uint16_t InSize);
    //在指定节点上分割一块区域,如果分割失败，返回nullptr
    //如果分割成功，返回分割出来的节点，需要手动将这个节点移出EmptyNodes
    std::shared_ptr<CTextureTreeNode> OcuppyWithNode(uint16_t InSize,std::shared_ptr<CTextureTreeNode> InNode);
    void GenerateBigTexture();

    //字符纹理映射
    TMap<std::shared_ptr<SFreeTypeGlyph>,SCharTexture> CharMap;


};